"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

require("core-js/modules/es.function.name");

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;

var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));

var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));

var _get2 = _interopRequireDefault(require("@babel/runtime/helpers/get"));

var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));

var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));

var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));

var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));

var _logger = _interopRequireDefault(require("./utils/logger.js"));

var _loader = require("./loader.js");

var _exception = require("./utils/exception.js");

function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2.default)(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2.default)(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2.default)(this, result); }; }

function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }

// For FireFox browser which supports `xhr.responseType = 'moz-chunked-arraybuffer'`
var MozChunkedLoader = /*#__PURE__*/function (_BaseLoader) {
  (0, _inherits2.default)(MozChunkedLoader, _BaseLoader);

  var _super = _createSuper(MozChunkedLoader);

  (0, _createClass2.default)(MozChunkedLoader, null, [{
    key: "isSupported",
    value: function isSupported() {
      try {
        var xhr = new XMLHttpRequest(); // Firefox 37- requires .open() to be called before setting responseType

        xhr.open('GET', 'https://example.com', true);
        xhr.responseType = 'moz-chunked-arraybuffer';
        return xhr.responseType === 'moz-chunked-arraybuffer';
      } catch (e) {
        _logger.default.w('MozChunkedLoader', e.message);

        return false;
      }
    }
  }]);

  function MozChunkedLoader(seekHandler, config) {
    var _this;

    (0, _classCallCheck2.default)(this, MozChunkedLoader);
    _this = _super.call(this, 'xhr-moz-chunked-loader');
    _this.TAG = 'MozChunkedLoader';
    _this._seekHandler = seekHandler;
    _this._config = config;
    _this._needStash = true;
    _this._xhr = null;
    _this._requestAbort = false;
    _this._contentLength = null;
    _this._receivedLength = 0;
    return _this;
  }

  (0, _createClass2.default)(MozChunkedLoader, [{
    key: "destroy",
    value: function destroy() {
      if (this.isWorking()) {
        this.abort();
      }

      if (this._xhr) {
        this._xhr.onreadystatechange = null;
        this._xhr.onprogress = null;
        this._xhr.onloadend = null;
        this._xhr.onerror = null;
        this._xhr = null;
      }

      (0, _get2.default)((0, _getPrototypeOf2.default)(MozChunkedLoader.prototype), "destroy", this).call(this);
    }
  }, {
    key: "open",
    value: function open(dataSource, range) {
      this._dataSource = dataSource;
      this._range = range;
      var sourceURL = dataSource.url;

      if (this._config.reuseRedirectedURL && dataSource.redirectedURL != undefined) {
        sourceURL = dataSource.redirectedURL;
      }

      var seekConfig = this._seekHandler.getConfig(sourceURL, range);

      this._requestURL = seekConfig.url;
      var xhr = this._xhr = new XMLHttpRequest();
      xhr.open('GET', seekConfig.url, true);
      xhr.responseType = 'moz-chunked-arraybuffer';
      xhr.onreadystatechange = this._onReadyStateChange.bind(this);
      xhr.onprogress = this._onProgress.bind(this);
      xhr.onloadend = this._onLoadEnd.bind(this);
      xhr.onerror = this._onXhrError.bind(this); // cors is auto detected and enabled by xhr
      // withCredentials is disabled by default

      if (dataSource.withCredentials) {
        xhr.withCredentials = true;
      }

      if ((0, _typeof2.default)(seekConfig.headers) === 'object') {
        var headers = seekConfig.headers;

        for (var key in headers) {
          if (headers.hasOwnProperty(key)) {
            xhr.setRequestHeader(key, headers[key]);
          }
        }
      } // add additional headers


      if ((0, _typeof2.default)(this._config.headers) === 'object') {
        var _headers = this._config.headers;

        for (var _key in _headers) {
          if (_headers.hasOwnProperty(_key)) {
            xhr.setRequestHeader(_key, _headers[_key]);
          }
        }
      }

      this._status = _loader.LoaderStatus.kConnecting;
      xhr.send();
    }
  }, {
    key: "abort",
    value: function abort() {
      this._requestAbort = true;

      if (this._xhr) {
        this._xhr.abort();
      }

      this._status = _loader.LoaderStatus.kComplete;
    }
  }, {
    key: "_onReadyStateChange",
    value: function _onReadyStateChange(e) {
      var xhr = e.target;

      if (xhr.readyState === 2) {
        // HEADERS_RECEIVED
        if (xhr.responseURL != undefined && xhr.responseURL !== this._requestURL) {
          if (this._onURLRedirect) {
            var redirectedURL = this._seekHandler.removeURLParameters(xhr.responseURL);

            this._onURLRedirect(redirectedURL);
          }
        }

        if (xhr.status !== 0 && (xhr.status < 200 || xhr.status > 299)) {
          this._status = _loader.LoaderStatus.kError;

          if (this._onError) {
            this._onError(_loader.LoaderErrors.HTTP_STATUS_CODE_INVALID, {
              code: xhr.status,
              msg: xhr.statusText
            });
          } else {
            throw new _exception.RuntimeException('MozChunkedLoader: Http code invalid, ' + xhr.status + ' ' + xhr.statusText);
          }
        } else {
          this._status = _loader.LoaderStatus.kBuffering;
        }
      }
    }
  }, {
    key: "_onProgress",
    value: function _onProgress(e) {
      if (this._status === _loader.LoaderStatus.kError) {
        // Ignore error response
        return;
      }

      if (this._contentLength === null) {
        if (e.total !== null && e.total !== 0) {
          this._contentLength = e.total;

          if (this._onContentLengthKnown) {
            this._onContentLengthKnown(this._contentLength);
          }
        }
      }

      var chunk = e.target.response;
      var byteStart = this._range.from + this._receivedLength;
      this._receivedLength += chunk.byteLength;

      if (this._onDataArrival) {
        this._onDataArrival(chunk, byteStart, this._receivedLength);
      }
    }
  }, {
    key: "_onLoadEnd",
    value: function _onLoadEnd(e) {
      if (this._requestAbort === true) {
        this._requestAbort = false;
        return;
      } else if (this._status === _loader.LoaderStatus.kError) {
        return;
      }

      this._status = _loader.LoaderStatus.kComplete;

      if (this._onComplete) {
        this._onComplete(this._range.from, this._range.from + this._receivedLength - 1);
      }
    }
  }, {
    key: "_onXhrError",
    value: function _onXhrError(e) {
      this._status = _loader.LoaderStatus.kError;
      var type = 0;
      var info = null;

      if (this._contentLength && e.loaded < this._contentLength) {
        type = _loader.LoaderErrors.EARLY_EOF;
        info = {
          code: -1,
          msg: 'Moz-Chunked stream meet Early-Eof'
        };
      } else {
        type = _loader.LoaderErrors.EXCEPTION;
        info = {
          code: -1,
          msg: e.constructor.name + ' ' + e.type
        };
      }

      if (this._onError) {
        this._onError(type, info);
      } else {
        throw new _exception.RuntimeException(info.msg);
      }
    }
  }]);
  return MozChunkedLoader;
}(_loader.BaseLoader);

var _default = MozChunkedLoader;
exports.default = _default;